package com.matrix;

import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;

@Slf4j
public class JarTools {

    public static void main(String[] args) throws Exception {
        String command;
        String prefix = "";
        if (OsInfo.isWindows()) {
            prefix = "cmd.exe /C ";
        }
        command = prefix + "mvn -T 4 -f pom1.xml dependency:copy-dependencies dependency:sources dependency:list -DoutputFile=list.txt";
        boolean result = downloadAndGetList(command);
        if (!result) {
            log.error("check command, [{}]", command);
            return;
        }
        long t1 = System.currentTimeMillis();
        String[] names = getNeedCompressFiles();
        long t2 = System.currentTimeMillis();
        log.info("getNeedCompressFiles cost {} ms", (t2 - t1));
        log.info("compress result:" + ZipUtil.zipCompress(names, Common.rootPath + File.separator + "dependency.zip", getRepoPath()));
        long end = System.currentTimeMillis();
        log.info("compress cost {}ms", (end - t2));
        log.info("all cost {}ms", (end - t1));
    }

    private static boolean downloadAndGetList(String command) {
        boolean result = false;
        try {
            log.info("command : {}", command);
            Process proc = Runtime.getRuntime().exec(command);
            InputStreamReader ir = new InputStreamReader(proc.getInputStream());
            LineNumberReader input = new LineNumberReader(ir);
            String line;
            while ((line = input.readLine()) != null) {
                System.out.println(line);
            }
            int exitVal = proc.waitFor(); // 阻塞当前线程，并等待外部程序中止后获取结果码
            result = exitVal == 0;
            log.info("下载jar包" + (result ? "成功" : "失败"));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return result;
    }

    private static String[] getNeedCompressFiles() throws IOException {
        List<String> lines = FileUtils.readLines(new File(Common.rootPath + File.separator + "list.txt"), Common.ENCODING);
        log.info("repoPath : {}", getRepoPath());
        Set<String> files = new HashSet<>();
        List<String> pomFiles = new ArrayList<>();
        for (int i = 2; i < lines.size(); i++) {
            Dependency dependency = Dependency.fromString(lines.get(i));
            if (dependency != null) {
                String path = getRepoPath() + File.separator + getDependencyRelativePath(dependency);
                log.info("compressPath : {}", path);
                File[] files0 = new File(path).listFiles();
                if (files0 != null) {
                    for (File file : files0) {
                        files.add(file.getPath());
                        if (file.getPath().endsWith(".pom")) {
                            pomFiles.add(file.getPath());
                        }
                    }
                }
            }
        }
        //get parent file
        Set<String> parentPaths = new HashSet<>();
        parentPaths = getParent(pomFiles, parentPaths);
        for (String path : parentPaths) {
            File[] files0 = new File(path).listFiles();
            log.info("parent compressPath : {}", path);
            if (files0 != null) {
                for (File file : files0) {
                    if (!files.contains(file.getPath())) {
                        files.add(file.getPath());
                    }
                }
            }
        }
        String[] names = new String[files.size()];
        names = files.toArray(names);
        return names;
    }

    private static Set<String> getParent(List<String> pomFiles, Set<String> parentPaths) throws IOException {
        for (String pom : pomFiles) {
            Dependency dependency = Dom4jUtil.getParentDependency(pom);
            if (dependency != null) {
                String path = getRepoPath() + File.separator + getDependencyRelativePath(dependency);
                parentPaths.add(path);
                List<String> parentPom = getPomFiles(dependency);
                if (parentPom.size() > 0) {
                    getParent(parentPom, parentPaths);
                }
            }
        }
        return parentPaths;
    }

    private static List<String> getPomFiles(Dependency dependency ){
        List<String> pomFiles = new ArrayList<>();
        try {
            if (dependency != null) {
                String path = getRepoPath() + File.separator + getDependencyRelativePath(dependency);
                File[] files0 = new File(path).listFiles();
                if (files0 != null) {
                    for (File file : files0) {
                        if (file.getPath().endsWith(".pom")) {
                            pomFiles.add(file.getPath());
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pomFiles;
    }

    private static String getRepoPath() throws IOException {
        return FileUtils.readFileToString(new File(Common.rootPath + File.separator + "repo.txt"), Common.ENCODING);
    }

    private static String groupIdToPath(String groupId) {
        return groupId.replace(".", File.separator);
    }

    private static String getDependencyRelativePath(Dependency dependency) {
        return groupIdToPath(dependency.getGroupId()) + File.separator + dependency.getArtifactId() + File.separator + dependency.getVersion();
    }

}
